package com.rainng.coursesystem.service.teacher;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.vod.upload.impl.UploadVideoImpl;
import com.aliyun.vod.upload.req.UploadStreamRequest;
import com.aliyun.vod.upload.resp.UploadStreamResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.vod.model.v20170321.GetVideoPlayAuthRequest;
import com.aliyuncs.vod.model.v20170321.GetVideoPlayAuthResponse;
import com.google.gson.Gson;
import com.rainng.coursesystem.dao.mapper.CourseResourceMapper;
import com.rainng.coursesystem.model.bo.CourseResourceDTO;
import com.rainng.coursesystem.model.entity.CourseResourceEntity;
import com.rainng.coursesystem.model.vo.response.ResultVO;
import com.rainng.coursesystem.service.BaseService;
import lombok.experimental.Accessors;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.awt.print.PrinterException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Service
public class VodService extends BaseService {

    @Value("${yun.alioss.access-key-id}")
    private  String accessKeyId;
    @Value("${yun.alioss.access-key-secret}")
    private String accessKeySecret;
    @Value("${yun.alioss.endpoint}")
    private String endpoint;
    @Value("${yun.alioss.bucket-name}")
    private String bucketName;

    @Autowired
    private CourseResourceMapper courseResourceMapper;

    List<String> videoExtensions = Arrays.asList(".mp4");
    List<String> pdfExtensions = Arrays.asList(".pdf");
    List<String> wordExtensions = Arrays.asList(".doc", ".docx");


    public ResultVO vodUpload(MultipartFile file) {
        // 视频文件上传
        // 视频标题（必选）

        // 任何上传方式文件名必须包含扩展名

        //获取文件的输入流
        InputStream inputStream = null;
        try {
            inputStream = file.getInputStream();
            //文件原名称
            String originalFilename = file.getOriginalFilename();

            //后缀
            String suffix = originalFilename.substring(originalFilename.lastIndexOf('.'));

            //文件上传后名称
            String title = originalFilename.substring(0, originalFilename.lastIndexOf("."));

            SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd");
            String filePath = format.format(new Date());
            String vodName = UUID.randomUUID().toString().replace("-", "");
            String fileName = filePath+"/"+vodName+suffix;


            String vid = testUploadStream(accessKeyId, accessKeySecret, title, fileName, inputStream);

            return result(vid);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 流式上传接口
     *
     * @param accessKeyId
     * @param accessKeySecret
     * @param title
     * @param fileName
     * @param inputStream
     */
    private static String testUploadStream(String accessKeyId, String accessKeySecret, String title, String fileName, InputStream inputStream) {
        UploadStreamRequest request = new UploadStreamRequest(accessKeyId, accessKeySecret, title, fileName, inputStream);


        UploadVideoImpl uploader = new UploadVideoImpl();
        UploadStreamResponse response = uploader.uploadStream(request);
        System.out.print("RequestId=" + response.getRequestId() + "\n");  //请求视频点播服务的请求ID
        if (response.isSuccess()) {
            System.out.print("VideoId=" + response.getVideoId() + "\n");

        } else { //如果设置回调URL无效，不影响视频上传，可以返回VideoId同时会返回错误码。其他情况上传失败时，VideoId为空，此时需要根据返回错误码分析具体错误原因
            System.out.print("VideoId=" + response.getVideoId() + "\n");
            System.out.print("ErrorCode=" + response.getCode() + "\n");
            System.out.print("ErrorMessage=" + response.getMessage() + "\n");
        }
        return response.getVideoId();
    }

    public ResultVO getAuth(String vid) {
        // Please ensure that the environment variables ALIBABA_CLOUD_ACCESS_KEY_ID and ALIBABA_CLOUD_ACCESS_KEY_SECRET are set.
        DefaultProfile profile = DefaultProfile
                .getProfile("cn-shanghai",
                        accessKeyId,
                        accessKeySecret);
        /** use STS Token
         DefaultProfile profile = DefaultProfile.getProfile(
         "<your-region-id>",           // The region ID
         System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"),       // The AccessKey ID of the RAM account
         System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"),   // The AccessKey Secret of the RAM account
         System.getenv("ALIBABA_CLOUD_SECURITY_TOKEN"));     // STS Token
         **/

        IAcsClient client = new DefaultAcsClient(profile);


        GetVideoPlayAuthRequest request = new GetVideoPlayAuthRequest();
        request.setVideoId(vid);

        try {
            GetVideoPlayAuthResponse response = client.getAcsResponse(request);
            System.out.println(new Gson().toJson(response));
            return result(response.getPlayAuth());
        } catch (ClientException e) {
            System.out.println("ErrCode:" + e.getErrCode());
            System.out.println("ErrMsg:" + e.getErrMsg());
            System.out.println("RequestId:" + e.getRequestId());
        }
        return null;
    }


    public ResultVO courseResourceUpLoad(Integer courseId, CourseResourceDTO dto) {

        MultipartFile file = dto.getFile();

        if (file.isEmpty()) {
            return null;
        }

        try {
            // 获取原始文件名
            String originalFilename = file.getOriginalFilename();
            // 截取原始文件名的后缀
            String extension = originalFilename.substring(originalFilename.lastIndexOf("."));
            // 构造新文件名称
            String objectName = UUID.randomUUID() + extension;
            // 文件的请求路径
            String filePath = upload(file.getBytes(), objectName);
            CourseResourceEntity entity = new CourseResourceEntity();
            entity.setCourseId(courseId);
            entity.setPath(filePath);
            entity.setName(dto.getName());
            if (videoExtensions.contains(extension)){
                //说明是视频类型
                entity.setType(0); // 视频（mp4)
            }else {
                entity.setType(1); // 文件（pdf或doc）
            }

            courseResourceMapper.insert(entity);

            return result(filePath);
        } catch (IOException e) {

        }
        return null;

    }

    public String upload(byte[] bytes, String objectName) {

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            // 创建PutObject请求。
            ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(bytes));
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (com.aliyun.oss.ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }

        // todo 自定义文件访问路径规则 https://BucketName.Endpoint/ObjectName
        StringBuilder stringBuilder = new StringBuilder("https://");
        stringBuilder
                .append(bucketName)
                .append(".")
                .append(endpoint)
                .append("/")
                .append(objectName);

        return stringBuilder.toString();
    }
}
